home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr44 / frasrc19.zip / LOADFDOS.C < prev    next >
C/C++ Source or Header  |  1995-01-12  |  15KB  |  402 lines

  1. /*
  2.     loadfdos.c - subroutine of loadfile.c (read_overlay) which sets
  3.          up video (mode, screen size).
  4.     This module is linked as an overlay, should only be called from loadfile.c
  5.  
  6.     This code was split to a separate module to isolate the DOS only aspects
  7.     of loading an image.  get_video_mode should return with:
  8.       return code 0 for ok, -1 for error or cancelled by user
  9.       video parameters setup for the mainline, in the dos case this means
  10.     setting initmode to video mode, based on this fractint.c will set up
  11.     for and call setvideomode
  12.       set viewwindow on if file going to be loaded into a view smaller than
  13.     physical screen, in this case also set viewreduction, viewxdots,
  14.     viewydots, and finalaspectratio
  15.       set skipxdots and skipydots, to 0 if all pixels are to be loaded,
  16.     to 1 for every 2nd pixel, 2 for every 3rd, etc
  17.  
  18.     In WinFract, at least initially, get_video_mode can do just the
  19.     following:
  20.       set overall image x & y dimensions (sxdots and sydots) to filexdots
  21.     and fileydots (note that filecolors is the number of colors in the
  22.     gif, not sure if that is of any use...)
  23.       if current window smaller than new sxdots and sydots, use scroll bars,
  24.     if larger perhaps reduce the window size? whatever
  25.       set viewwindow to 0 (no need? it always is for now in windows vsn?)
  26.       set finalaspectratio to .75 (ditto?)
  27.       set skipxdots and skipydots to 0
  28.       return 0
  29.  
  30. */
  31.  
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <math.h>
  36. #include "fractint.h"
  37. #include "helpdefs.h"
  38. #include "prototyp.h"
  39.  
  40. /* routines in this module    */
  41.  
  42. static int    vidcompare(VOIDCONSTPTR ,VOIDCONSTPTR );
  43. static void   format_vid_inf(int i,char *err,char *buf);
  44. static double vid_aspect(int tryxdots,int tryydots);
  45. static void   format_item(int,char *);
  46. static int    check_modekey(int,int);
  47.  
  48. struct vidinf {
  49.    int entnum;       /* videoentry subscript */
  50.    unsigned flags; /* flags for sort's compare, defined below */
  51.    };
  52. /* defines for flags; done this way instead of bit union to ensure ordering;
  53.    these bits represent the sort sequence for video mode list */
  54. #define VI_EXACT 0x8000 /* unless the one and only exact match */
  55. #define VI_NOKEY   512    /* if no function key assigned */
  56. #define VI_DISK1   256    /* disk video and size not exact */
  57. #define VI_SSMALL  128    /* screen smaller than file's screen */
  58. #define VI_SBIG     64    /* screen bigger than file's screen */
  59. #define VI_VSMALL   32    /* screen smaller than file's view */
  60. #define VI_VBIG     16    /* screen bigger than file's view */
  61. #define VI_CSMALL    8    /* mode has too few colors */
  62. #define VI_CBIG      4    /* mode has excess colors */
  63. #define VI_DISK2     2    /* disk video */
  64. #define VI_ASPECT    1    /* aspect ratio bad */
  65.  
  66.  
  67. static int vidcompare(VOIDCONSTPTR p1,VOIDCONSTPTR p2)
  68. {
  69.    struct vidinf CONST *ptr1,*ptr2;
  70.    ptr1 = (struct vidinf CONST *)p1;
  71.    ptr2 = (struct vidinf CONST *)p2;
  72.    if (ptr1->flags < ptr2->flags) return(-1);
  73.    if (ptr1->flags > ptr2->flags) return(1);
  74.    if (vidtbl[ptr1->entnum].keynum < vidtbl[ptr2->entnum].keynum) return(-1);
  75.    if (vidtbl[ptr1->entnum].keynum > vidtbl[ptr2->entnum].keynum) return(1);
  76.    if (ptr1->entnum < ptr2->entnum) return(-1);
  77.    return(1);
  78. }
  79.  
  80. static void format_vid_inf(int i,char *err,char *buf)
  81. {
  82.    char kname[5];
  83.    far_memcpy((char far *)&videoentry,(char far *)&vidtbl[i],
  84.           sizeof(videoentry));
  85.    vidmode_keyname(videoentry.keynum,kname);
  86.    sprintf(buf,"%-5s %-25s %-4s %4d %4d %3d %-25s",  /* 76 chars */
  87.        kname, videoentry.name, err,
  88.        videoentry.xdots, videoentry.ydots,
  89.        videoentry.colors, videoentry.comment);
  90.    videoentry.xdots = 0; /* so tab_display knows to display nothing */
  91. }
  92.  
  93. static double vid_aspect(int tryxdots,int tryydots)
  94. {  /* calc resulting aspect ratio for specified dots in current mode */
  95.    return (double)tryydots / (double)tryxdots
  96.     * (double)videoentry.xdots / (double)videoentry.ydots
  97.     * screenaspect;
  98.    }
  99.  
  100.  
  101. static struct vidinf *vidptr;
  102.  
  103. int get_video_mode(struct fractal_info *info,struct ext_blk_3 *blk_3_info)
  104. {
  105.    static FCODE o_hdg2[]={"key...name......................err..xdot.ydot.clr.comment.................."};
  106.    static FCODE o_warning[]={"\nWARNING: non-standard aspect ratio; loading will change your <v>iew settings"};
  107.    static FCODE o_select_msg[]={"\
  108. Select a video mode.  Use the cursor keypad to move the pointer.\n\
  109. Press ENTER for selected mode, or use a video mode function key.\n\
  110. Press F1 for help, "};
  111.    char far *hdg2, far *warning, far *select_msg, far *ptr;
  112.    struct vidinf vid[MAXVIDEOMODES];
  113.    int i,j;
  114.    int gotrealmode;
  115.    double ftemp,ftemp2;
  116.    unsigned tmpflags;
  117.  
  118.    int tmpxdots,tmpydots;
  119.    float tmpreduce;
  120.    char *nameptr;
  121.    int    *attributes;
  122.    int oldhelpmode;
  123.    VIDEOINFO *vident;
  124.    
  125.    /* save overlayed strings to extraseg memory */
  126.    ptr = (char far *)MK_FP(extraseg,ENDVID);  /* ENDVID is to avoid videotable */
  127.    hdg2 = ptr;
  128.    ptr += sizeof(o_hdg2);
  129.    warning = ptr;
  130.    ptr += sizeof(o_warning);
  131.    select_msg = ptr;
  132.    far_strcpy(hdg2,o_hdg2);
  133.    far_strcpy(warning,o_warning);
  134.    far_strcpy(select_msg,o_select_msg);
  135.    
  136.    initmode = -1;
  137.    load_fractint_cfg(0); /* get fractint.cfg into *vidtbl (== extraseg) */
  138.  
  139.    /* try to find exact match for vid mode */
  140.    for (i = 0; i < vidtbllen; ++i) {
  141.       vident = &vidtbl[i];
  142.       if (info->xdots == vident->xdots && info->ydots == vident->ydots
  143.     && filecolors == vident->colors
  144.     && info->videomodeax == vident->videomodeax
  145.     && info->videomodebx == vident->videomodebx
  146.     && info->videomodecx == vident->videomodecx
  147.     && info->videomodedx == vident->videomodedx
  148.     && info->dotmode%100 == vident->dotmode%100) {
  149.      initmode = i;
  150.      break;
  151.      }
  152.       }
  153.  
  154.    if (initmode == -1) /* try to find very good match for vid mode */
  155.       for (i = 0; i < vidtbllen; ++i) {
  156.      vident = &vidtbl[i];
  157.      if (info->xdots == vident->xdots && info->ydots == vident->ydots
  158.        && filecolors == vident->colors) {
  159.         initmode = i;
  160.         break;
  161.         }
  162.      }
  163.  
  164.    /* setup table entry for each vid mode, flagged for how well it matches */
  165.    for (i = 0; i < vidtbllen; ++i) {
  166.       far_memcpy((char far *)&videoentry,(char far *)&vidtbl[i],
  167.          sizeof(videoentry));
  168.       tmpflags = VI_EXACT;
  169.       if (videoentry.keynum == 0)
  170.      tmpflags |= VI_NOKEY;
  171.       if (info->xdots > videoentry.xdots || info->ydots > videoentry.ydots)
  172.      tmpflags |= VI_SSMALL;
  173.       else if (info->xdots < videoentry.xdots || info->ydots < videoentry.ydots)
  174.      tmpflags |= VI_SBIG;
  175.       if (filexdots > videoentry.xdots || fileydots > videoentry.ydots)
  176.      tmpflags |= VI_VSMALL;
  177.       else if (filexdots < videoentry.xdots || fileydots < videoentry.ydots)
  178.      tmpflags |= VI_VBIG;
  179.       if (filecolors > videoentry.colors)
  180.      tmpflags |= VI_CSMALL;
  181.       if (filecolors < videoentry.colors)
  182.      tmpflags |= VI_CBIG;
  183.       if (i == initmode)
  184.      tmpflags -= VI_EXACT;
  185.       if (videoentry.dotmode%100 == 11) {
  186.      tmpflags |= VI_DISK2;
  187.      if ((tmpflags & (VI_SBIG+VI_SSMALL+VI_VBIG+VI_VSMALL)) != 0)
  188.         tmpflags |= VI_DISK1;
  189.      }
  190.       if (fileaspectratio != 0 && videoentry.dotmode%100 != 11
  191.     && (tmpflags & VI_VSMALL) == 0) {
  192.      ftemp = vid_aspect(filexdots,fileydots);
  193.      if ( ftemp < fileaspectratio * 0.98
  194.        || ftemp > fileaspectratio * 1.02)
  195.         tmpflags |= VI_ASPECT;
  196.      }
  197.       vid[i].entnum = i;
  198.       vid[i].flags  = tmpflags;
  199.       }
  200.  
  201. #ifndef XFRACT
  202.    gotrealmode = 0;
  203.    if (initmode < 0 || (askvideo && !initbatch)) {
  204.       /* no exact match or (askvideo=yes and batch=no), talk to user */
  205.  
  206.       qsort(vid,vidtbllen,sizeof(vid[0]),vidcompare); /* sort modes */
  207.  
  208.       attributes = (int *)&dstack[1000];
  209.       for (i = 0; i < vidtbllen; ++i)
  210.      attributes[i] = 1;
  211.       vidptr = &vid[0]; /* for format_item */
  212.  
  213.       /* format heading */
  214.       if (info->info_id[0] == 'G')
  215.      strcpy(temp1,"      Non-fractal GIF");
  216.       else {
  217.      nameptr = curfractalspecific->name;
  218.      if (*nameptr == '*') ++nameptr;
  219.       if (display3d) nameptr = "3D Transform";
  220.      if ((!strcmp(nameptr,"formula")) ||
  221.          (!strcmp(nameptr,"lsystem")) ||
  222.          (!strncmp(nameptr,"ifs",3))) /* for ifs and ifs3d */
  223.            sprintf(temp1,"Type: %s -> %s",nameptr,blk_3_info->form_name);
  224.      else
  225.        sprintf(temp1,"Type: %s",nameptr);
  226.      }
  227.       sprintf((char *)dstack,"File: %-44s  %d x %d x %d\n%-52s",
  228.          readname,filexdots,fileydots,filecolors,temp1);
  229.       if (info->info_id[0] != 'G') {
  230.      if (save_system)
  231.         strcat((char *)dstack,"WinFract ");
  232.      sprintf(temp1,"v%d.%01d",save_release/100,(save_release%100)/10);
  233.      if (save_release%100) {
  234.         i = strlen(temp1);
  235.         temp1[i] = (char)((save_release%10) + '0');
  236.         temp1[i+1] = 0;
  237.         }
  238.      if (save_system == 0 && save_release <= 1410)
  239.         strcat(temp1," or earlier");
  240.      strcat((char *)dstack,temp1);
  241.      }
  242.       strcat((char *)dstack,"\n");
  243.       if (info->info_id[0] != 'G' && save_system == 0)
  244.      if (initmode < 0)
  245.         strcat((char *)dstack,"Saved in unknown video mode.");
  246.      else {
  247.         format_vid_inf(initmode,"",temp1);
  248.         strcat((char *)dstack,temp1);
  249.         }
  250.       if (fileaspectratio != 0 && fileaspectratio != screenaspect)
  251.      far_strcat((char *)dstack,warning);
  252.       strcat((char *)dstack,"\n");
  253.       /* set up instructions */
  254.       far_strcpy(temp1,select_msg);
  255.       if (info->info_id[0] != 'G')
  256.      strcat(temp1,"TAB for fractal information, ");
  257.       strcat(temp1,"ESCAPE to back out.");
  258.  
  259.       oldhelpmode = helpmode;
  260.       helpmode = HELPLOADFILE;
  261.       i = fullscreen_choice(0,(char *)dstack,hdg2,temp1,vidtbllen,NULL,attributes,
  262.                      1,13,76,0,format_item,NULL,NULL,check_modekey);
  263.       helpmode = oldhelpmode;
  264.       if (i == -1)
  265.      return(-1);
  266.       if (i < 0) { /* returned -100 - videotable entry number */
  267.      initmode = -100 - i;
  268.      gotrealmode = 1;
  269.      }
  270.       else
  271.      initmode = vid[i].entnum;
  272.       }
  273. #else
  274.       initmode = 0;
  275.       j = vidtbl[0].keynum;
  276.       gotrealmode = 0;
  277. #endif
  278.  
  279.    if (gotrealmode == 0) { /* translate from temp table to permanent */
  280.       if ((j = vidtbl[i=initmode].keynum) != 0) {
  281.      for (initmode = 0; initmode < MAXVIDEOTABLE-1; ++initmode)
  282.         if (videotable[initmode].keynum == j) break;
  283.      if (initmode >= MAXVIDEOTABLE-1) j = 0;
  284.      }
  285.       if (j == 0) /* mode has no key, add to reserved slot at end */
  286.      far_memcpy((char far *)&videotable[initmode=MAXVIDEOTABLE-1],
  287.             (char far *)&vidtbl[i],sizeof(*vidtbl));
  288.       }
  289.  
  290.    /* ok, we're going to return with a video mode */
  291.  
  292.    far_memcpy((char far *)&videoentry,(char far *)&videotable[initmode],
  293.           sizeof(videoentry));
  294.  
  295.    skipxdots = skipydots = 0; /* set for no reduction */
  296.    if (videoentry.xdots < filexdots || videoentry.ydots < fileydots) {
  297.       /* set up to load only every nth pixel to make image fit */
  298.       if (calc_status != 4) /* if not complete */
  299.           calc_status = 0;  /* can't resume anyway */
  300.       skipxdots = skipydots = 1;
  301.       while (skipxdots * videoentry.xdots < filexdots) ++skipxdots;
  302.       while (skipydots * videoentry.ydots < fileydots) ++skipydots;
  303.       i = j = 0;
  304.       for(;;) {
  305.      tmpxdots = (filexdots + skipxdots - 1) / skipxdots;
  306.      tmpydots = (fileydots + skipydots - 1) / skipydots;
  307.      if (fileaspectratio == 0 || videoentry.dotmode%100 == 11)
  308.         break;
  309.      /* reduce further if that improves aspect */
  310.      if ((ftemp = vid_aspect(tmpxdots,tmpydots)) > fileaspectratio) {
  311.         if (j) break; /* already reduced x, don't reduce y */
  312.         ftemp2 = vid_aspect(tmpxdots,(fileydots+skipydots)/(skipydots+1));
  313.         if (ftemp2 < fileaspectratio
  314.           && ftemp/fileaspectratio *0.9 <= fileaspectratio/ftemp2)
  315.            break; /* further y reduction is worse */
  316.         ++skipydots;
  317.         ++i;
  318.         }
  319.      else {
  320.         if (i) break; /* already reduced y, don't reduce x */
  321.         ftemp2 = vid_aspect((filexdots+skipxdots)/(skipxdots+1),tmpydots);
  322.         if (ftemp2 > fileaspectratio
  323.           && fileaspectratio/ftemp *0.9 <= ftemp2/fileaspectratio)
  324.            break; /* further x reduction is worse */
  325.         ++skipxdots;
  326.         ++j;
  327.         }
  328.      }
  329.       filexdots = tmpxdots;
  330.       fileydots = tmpydots;
  331.       --skipxdots;
  332.       --skipydots;
  333.       }
  334.  
  335.    if ((finalaspectratio = fileaspectratio) == 0) /* assume display correct */
  336.       finalaspectratio = (float)vid_aspect(filexdots,fileydots);
  337.    if (finalaspectratio >= screenaspect-0.02
  338.      && finalaspectratio <= screenaspect+0.02)
  339.       finalaspectratio = screenaspect;
  340.    i = (int)(finalaspectratio * 1000.0 + 0.5);
  341.    finalaspectratio = (float)(i/1000.0); /* chop precision to 3 decimals */
  342.  
  343.    /* setup view window stuff */
  344.    viewwindow = viewxdots = viewydots = 0;
  345.    if (filexdots != videoentry.xdots || fileydots != videoentry.ydots) {
  346.       /* image not exactly same size as screen */
  347.       viewwindow = 1;
  348.       ftemp = finalaspectratio
  349.         * (double)videoentry.ydots / (double)videoentry.xdots
  350.         / screenaspect;
  351.       if (finalaspectratio <= screenaspect) {
  352.      i = (int)((double)videoentry.xdots / (double)filexdots * 20.0 + 0.5);
  353.      tmpreduce = (float)(i/20.0); /* chop precision to nearest .05 */
  354.      i = (int)((double)videoentry.xdots / tmpreduce + 0.5);
  355.      j = (int)((double)i * ftemp + 0.5);
  356.      }
  357.       else {
  358.      i = (int)((double)videoentry.ydots / (double)fileydots * 20.0 + 0.5);
  359.      tmpreduce = (float)(i/20.0); /* chop precision to nearest .05 */
  360.      j = (int)((double)videoentry.ydots / tmpreduce + 0.5);
  361.      i = (int)((double)j / ftemp + 0.5);
  362.      }
  363.       if (i != filexdots || j != fileydots) { /* too bad, must be explicit */
  364.      viewxdots = filexdots;
  365.      viewydots = fileydots;
  366.      }
  367.       else
  368.      viewreduction = tmpreduce; /* ok, this works */
  369.       }
  370.    if (fabs(finalaspectratio - screenaspect) > .00001 || viewxdots != 0 ) {
  371.       static FCODE msg[] = {"\
  372. Warning: <V>iew parameters are being set to non-standard values.\n\
  373. Remember to reset them when finished with this image!"};
  374.       stopmsg(4,msg);
  375.       }
  376.  
  377.    return(0);
  378. }
  379.  
  380. static void format_item(int choice,char *buf)
  381. {
  382.    char errbuf[10];
  383.    unsigned tmpflags;
  384.    errbuf[0] = 0;
  385.    tmpflags = vidptr[choice].flags;
  386.    if (tmpflags & (VI_VSMALL+VI_CSMALL+VI_ASPECT)) strcat(errbuf,"*");
  387.    if (tmpflags & VI_VSMALL) strcat(errbuf,"R");
  388.    if (tmpflags & VI_CSMALL) strcat(errbuf,"C");
  389.    if (tmpflags & VI_ASPECT) strcat(errbuf,"A");
  390.    if (tmpflags & VI_VBIG)   strcat(errbuf,"v");
  391.    if (tmpflags & VI_CBIG)   strcat(errbuf,"c");
  392.    format_vid_inf(vidptr[choice].entnum,errbuf,buf);
  393. }
  394.  
  395. static int check_modekey(int curkey,int choice)
  396. {
  397.    int i;
  398.    i=choice; /* avoid warning */
  399.    return (((i = check_vidmode_key(0,curkey)) >= 0) ? -100-i : 0);
  400. }
  401.  
  402.